
#ifdef in_PC
#include "Lily_help.h"
#else
#include "Lily_help.h"
#endif // in_PC

volatile uint32_t _tp_front, _tp_rear;
Tasks_def _tp_tasks_[Tasks_LEN];
void tp_addTask(Tasks_def task)
{
	_tp_tasks_[_tp_rear++] = task;
	if (_tp_rear >= Tasks_LEN)
		_tp_rear = 0;
#ifdef in_debug
	if (_tp_rear == _tp_front)
	{
		lily_out("[tasks.c/addTask_]:tasks over flow\a\n");
		return;
	}
#endif // in_debug
}

void tp_endTask(Tasks_def task) // trash
{
	int32_t i;
	for (i = _tp_front; i != _tp_rear;)
	{
		if (_tp_tasks_[i] == task)
			break;
		i++;
		if (i == Tasks_LEN)
			i = 0;
	}
	if (i == _tp_rear)
		return;
	int32_t j = i, next;
	while (j != _tp_rear)
	{
		next = j + 1;
		if (next == Tasks_LEN)
			next = 0;
		_tp_tasks_[j] = _tp_tasks_[next];
		j = next;
	}
}
void tp_endTaskAt(char index)
{
	int32_t j = index, next;
	while (j != _tp_rear)
	{
		next = j + 1;
		if (next == Tasks_LEN)
			next = 0;
		_tp_tasks_[j] = _tp_tasks_[next];
		j = next;
	}
}
uint32_t tp_hadTask(Tasks_def task)
{
	uint32_t b = 0;
	uint32_t i;

	for (i = _tp_front; i != _tp_rear;)
	{
		if (_tp_tasks_[i] == task)
		{
			b = i;
			break;
		}

		if (++i == Tasks_LEN)
			i = 0;
	}
	return b;
}

void tp_run_tasks()
{
	int32_t i;
	while (1)
	{
		i = _tp_rear;
		while (_tp_front != i)
		{
			if (!_tp_tasks_[_tp_front])
			{
				lily_out("null ptr");
				if (++_tp_front >= Tasks_LEN)
					_tp_front = 0;
				continue;
			}
			if (_tp_tasks_[_tp_front]() == 1)
				tp_addTask(_tp_tasks_[_tp_front]);
			if (++_tp_front == Tasks_LEN)
				_tp_front = 0;
		}
	}
}
void tp_run_tasks_once()
{
	while (_tp_front != _tp_rear)
	{
		if (!_tp_tasks_[_tp_front])
		{
			if (++_tp_front >= Tasks_LEN)
				_tp_front = 0;
			continue;
		}
		if (_tp_tasks_[_tp_front]() == 1)
			tp_addTask(_tp_tasks_[_tp_front]);
		if (++_tp_front == Tasks_LEN)
			_tp_front = 0;
	}
}
#define queue_len 16
static TasksArg_def fs_arg[queue_len];
static void *args[queue_len];
static char queue_front = 0, queue_back = 0;
int32_t delegate_task_for_args(void);
void tp_addTaskArg(TasksArg_def f, void *arg)
{
#ifdef in_debug
	if (f == NULL)
	{
		lily_out("[tasks.c/addTaskArg]:null ptr");
		return;
	}
#endif // in_debug

	fs_arg[(int32_t)queue_back] = f;
	args[(int32_t)queue_back++] = arg;
	if (queue_back >= queue_len)
		queue_back = 0;
	if (!tp_hadTask(delegate_task_for_args))
		tp_addTask(delegate_task_for_args);
#ifdef in_debug
	if (queue_back == queue_front)
	{
		lily_out("[tasks.c/addTaskArg]:over flow\a\n");
		return;
	}
#endif // in_debug
}

int32_t delegate_task_for_args()
{
	static int32_t code;
	TasksArg_def f = fs_arg[(int32_t)queue_front];
	void *a = args[(int32_t)queue_front];
	code = f(a);   // 0->end, 1-> again
	if (code <= 0) // code==0
	{
		// if return 0, pop
		queue_front++;
		if (queue_front >= queue_len)
			queue_front = 0;
	}
	if (queue_back == queue_front)
		return 0;
	return 1;
}
